package state


import ."api"
import "fmt"


// 将空值入栈
func (self *luaState) PushNil() {

	self.stack.push(nil)
}


// 将布尔值入栈
func (self *luaState) PushBoolean(b bool) {

	self.stack.push(b)
}


// 将整数入栈
func (self *luaState) PushInteger(n int64) {

	self.stack.push(n)
}


// 将浮点数入栈
func (self *luaState) PushNumber(n float64) {

	self.stack.push(n)
}


// 将字符串入栈
func (self *luaState) PushString(s string) {

	self.stack.push(s)
}


// 接收一个Go函数参数，把它转变成Go闭包后推入栈顶
func (self *luaState) PushGoFunction(f GoFunction) {

	self.stack.push(newGoClosure(f, 0))  // 第二个参数传入0, 表示upvalue数量为0
}


// 由于全局环境也只是个普通的Lua表，所以GetTable()和SetTable()等表操作方法也同样适用于它
// 不过要使用这些方法，必须把全局环境先放入栈里
// PushGlobalTable()方法就是用来做这件事的
// 它把全局环境推入栈顶以备后续操作使用
func (self *luaState) PushGlobalTable() {

	global := self.registry.get(LUA_RIDX_GLOBALS)

	self.stack.push(global)

}

// PushGlobalTable另一种实现
/*
func (self *luaState) PushGlobalTable() {

	self.GetI(LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)

}
*/


// 专门给全局环境注册Go函数值
// 该方法仅操作全局环境，字段名和Go函数从参数传入，不改变Lua栈的状态
func (self *luaState) Register(name string, f GoFunction) {

	self.PushGoFunction(f)

	self.SetGlobal(name)

}


// 类似于PushGoFunction()，也是把Go函数转变成Go闭包推入栈顶
// 区别在于PushGoClosure()会先从栈顶弹出n个Lua值
// 这些值会成为Go闭包的Upvalue
// 留在栈顶的是Go闭包
func (self  *luaState) PushGoClosure(f GoFunction, n int) {

	closure := newGoClosure(f, n)

	for i := n; i > 0; i-- {

		val := self.stack.pop()
		closure.upvals[i-1] = &upvalue{&val}

	}

	self.stack.push(closure)

}


func (self *luaState) PushFString(fmtStr string, a ...interface{}) {
	str := fmt.Sprintf(fmtStr, a...)
	self.stack.push(str)
}


// 把线程推入栈顶, 返回的布尔值表示线程是否是主线程
func (self *luaState) PushThread() bool {
	self.stack.push(self)
	return self.isMainThread()
}